﻿using DevExpress.Data;
using DevExpress.Utils;
using DevExpress.Utils.Design;
using DevExpress.Utils.Menu;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Menu;
using DevExpress.XtraGrid.Registrator;
using DevExpress.XtraGrid.Views.BandedGrid;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors.Controls;
using XCI.Core;
using XCI.Extensions;
using XCI.Helper;
using XCI.Setting;

namespace XCI.Windows
{
    [System.ComponentModel.DesignerCategory("Code")]
    public class GridControlPlus : GridControl, ISettingSerializer
    {
        private readonly Stopwatch sw = new Stopwatch();
        private bool isInit;
        private bool isDataLoading;
        private Type _modelType;
        private ApiModel _apiModelInfo;
        private int currentMaxRecordLength;
        private bool isSorting;
        private VirtualServerModeSource _virtualServerModeSource;
        private bool _virtualServerModeSourceInit;
        private int _virtualSourcePageIndex;

        #region Register

        protected override BaseView CreateDefaultView()
        {
            return CreateView(GridViewPlusInfoRegistrator.GridViewName);
        }

        protected override void RegisterAvailableViewsCore(InfoCollection collection)
        {
            base.RegisterAvailableViewsCore(collection);
            collection.Add(new GridViewPlusInfoRegistrator());
            collection.Add(new BandedGridViewPlusInfoRegistrator());
            collection.Add(new AdvBandedGridViewPlusInfoRegistrator());
        }

        #endregion


        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public SettingStoreManager SettingManager { get; set; }

        /// <summary>
        /// 配置标识
        /// </summary>
        [Category("XCI"), Description("配置标识")]
        [SmartTagProperty("配置标识", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public virtual string Id { get; set; } = $"grid-{StringHelper.Guid()}";

        /// <summary>
        /// 实体类型
        /// </summary>
        [Browsable(false), Description("实体类型"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Type ModelType
        {
            get => _modelType;
            set
            {
                _modelType = value;
                if (WinFormHelper.IsDesignMode()) return;
                _apiModelInfo = ApiModelManager.Get(ModelType);
                if (_apiModelInfo?.PrimaryKey != null) PrimaryKeyFieldName = _apiModelInfo.PrimaryKey.Name;
            }
        }

        /// <summary>
        /// 实体元数据
        /// </summary>
        [Browsable(false), Description("实体元数据"),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ApiModel ApiModelInfo => _apiModelInfo;

        /// <summary>
        /// 主键字段名
        /// </summary>
        [Category("XCI"), Description("主键字段名"), DefaultValue("Id")]
        [SmartTagProperty("主键字段名", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public virtual string PrimaryKeyFieldName { get; set; } = "Id";

        /// <summary>
        /// 允许自定义配置
        /// </summary>
        [Category("XCI"), Description("允许自定义配置"), DefaultValue(true)]
        [SmartTagProperty("允许自定义配置", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public bool AllowCustomSetting { get; set; } = true;

        [Category("XCI"), Description("自动加载配置"), DefaultValue(true)]
        [SmartTagProperty("自动加载配置", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public bool AutoLoadSetting { get; set; } = true;

        [Category("XCI"), Description("是否保留数据状态"), DefaultValue(true)]
        [SmartTagProperty("是否保留数据状态", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public bool ReserveDataStatus { get; set; } = true;

        [Category("XCI"), Description("允许服务端排序"), DefaultValue(true)]
        [SmartTagProperty("允许服务端排序", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public bool AllowServerSorting { get; set; } = true;


        [Category("XCI"), Description("是否显示数据加载提示面板"), DefaultValue(true)]
        [SmartTagProperty("是否显示数据加载提示面板", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public bool IsShowDataLoadingPanel { get; set; } = true;


        [Category("XCI"), Description("允许计算序号宽度"), DefaultValue(true)]
        [SmartTagProperty("允许计算序号宽度", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public bool AllowCalcIndicatorWidth { get; set; } = true;

        [Category("XCI"), Description("执行耗时显示BarItem控件"), DefaultValue(null)]
        public BarItem ElapsedTimeItem { get; set; }

        [Category("XCI"), Description("执行耗时显示控件"), DefaultValue(null)]
        public Control ElapsedTimeControl { get; set; }

        [Category("XCI"), Description("分页控件"), DefaultValue(null)]
        public XtraUserControl PagingControl { get; set; }

        /// <summary>
        /// 执行耗时
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public TimeSpan ElapsedTimeSpan { get; private set; }

        /// <summary>
        /// 搜索框
        /// </summary>
        [Category("XCI"), Description("搜索框"), DefaultValue(null),]
        public BaseEdit FilterEdit { get; set; }

        [Category("XCI"), Description("自动生成右键菜单"), DefaultValue(true)]
        [SmartTagProperty("自动生成右键菜单", "XCI", SmartTagActionType.RefreshAfterExecute)]
        public bool AutoPopupMenu { get; set; } = true;

        [Category("XCI"), Description("右键菜单控件"), DefaultValue(null)]
        public PopupMenu PopupMenu { get; set; }

        [Category("XCI"), Description("加载配置之前事件")]
        public event EventHandler<EventArgs> BeforeRestoreLayout;

        [Category("XCI"), Description("加载配置之后事件")]
        public event EventHandler<EventArgs> AfterRestoreLayout;

        [Category("XCI"), Description("获取过滤对象事件")]
        public event EventHandler<DetectFilterEventArgs> DetectFilter;

        [Category("XCI"), Description("数据加载事件")]
        public event EventHandler<LoadDataEventArgs> LoadData;

        [Category("XCI"), Description("数据加载之前事件")]
        public event EventHandler<LoadDataEventArgs> BeforeLoadData;

        [Category("XCI"), Description("数据加载之后事件")]
        public event EventHandler<AfterLoadPagingDataEventArgs> AfterLoadData;

        [Category("XCI"), Description("行删除事件")]
        public event EventHandler<DeleteDataEventArgs> DeleteData;

        [Category("XCI"), Description("行选择变化事件")]
        public event EventHandler<EventArgs> RowSelectionChanged;

        [Category("XCI"), Description("行双击事件")]
        public event EventHandler<EventArgs> RowDoubleClick;

        [Category("XCI"), Description("控件开始初始化事件")]
        public event EventHandler<EventArgs> BeforeInitialize;
        [Category("XCI"), Description("控件初始化结束事件")]
        public event EventHandler<EventArgs> AfterInitialize;


        protected virtual void OnBeforeInitialize()
        {
            BeforeInitialize?.Invoke(this, EventArgs.Empty);
        }

        protected virtual void OnAfterInitialize()
        {
            AfterInitialize?.Invoke(this, EventArgs.Empty);
        }

        /// <summary>
        /// 获取或者设置表格数据源
        /// </summary>
        public override object DataSource
        {
            get => base.DataSource;
            set
            {
                if (WinFormHelper.IsDesignMode()) return;
                if (value == null)
                {
                    base.DataSource = null;
                    return;
                }

                var currentDataSource = base.DataSource;
                if (ReserveDataStatus && currentDataSource != null && currentDataSource is IList source && value is IList listDataSource)
                {
                    source.Clear();
                    foreach (var item in listDataSource)
                    {
                        source.Add(item);
                    }
                    RefreshDataSource();
                }
                else
                {
                    base.DataSource = value;
                }
            }
        }

        #region 公共属性

        /// <summary>
        /// 是否正在加载数据中
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsDataLoading => isDataLoading;

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsColumnView => MainView is ColumnView;

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsBandedGridView => MainView is BandedGridView;

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ColumnView CurrentColumnView => MainView as ColumnView;

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsGridView => MainView is GridView;

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public GridView CurrentGridView => MainView as GridView;

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public BandedGridView CurrentBandedGridView => MainView as BandedGridView;

        /// <summary>
        /// 选中行索引(从0开始)
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int SelectedIndex
        {
            get
            {
                //if (CurrentColumnView.OptionsSelection.MultiSelect)//多选模式
                //{
                //    var selectedRowHandles = CurrentColumnView.GetSelectedRows();
                //    if (selectedRowHandles.Length > 0) return selectedRowHandles[0];
                //    return -1;
                //}
                //else //单选模式
                //{
                //    return CurrentColumnView.FocusedRowHandle;
                //}
                return CurrentColumnView.FocusedRowHandle;
            }
        }

        /// <summary>
        /// 选中的主键
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string SelectedId => GetRecordId(SelectedIndex);

        /// <summary>
        /// 选中行索引数组
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int[] SelectedIndexList
        {
            get
            {
                if (CurrentColumnView.OptionsSelection.MultiSelect) //多选模式
                {
                    return CurrentColumnView.GetSelectedRows();
                }
                else //单选模式
                {
                    return CurrentColumnView.FocusedRowHandle < 0 ? new int[0] : new[] { CurrentColumnView.FocusedRowHandle };
                }
            }
        }

        /// <summary>
        /// 获取勾选的主键数组
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string[] SelectedIdList
        {
            get
            {
                var idList = new List<string>();
                foreach (var item in SelectedIndexList)
                {
                    if (item < 0) continue;
                    idList.Add(GetRecordId(item));
                }
                return idList.ToArray();
            }
        }

        /// <summary>
        /// 获取勾选的主键字符串,用逗号分开
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string SelectedIds => SelectedIdList.JoinString();

        /// <summary>
        /// 当前焦点是否是第一行
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsFirstFocus => !CurrentColumnView.IsEmpty && SelectedIndex == CurrentColumnView.GetVisibleRowHandle(0);

        /// <summary>
        /// 当前焦点是否是最后一行
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsLastFocus => !CurrentColumnView.IsEmpty && SelectedIndex == CurrentColumnView.GetVisibleRowHandle(CurrentColumnView.RowCount - 1);

        /// <summary>
        /// 当前是否选中多条
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool HasMultiSelected
        {
            get
            {
                if (CurrentColumnView.OptionsSelection.MultiSelect)//多选模式
                {
                    return CurrentColumnView.GetSelectedRows().Length > 1;
                }
                //单选模式
                return false;
            }
        }

        /// <summary>
        /// 表格中是否有数据
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool HasData => CurrentColumnView.RowCount > 0;

        /// <summary>
        /// 是否单选数据
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool HasSingleSelected
        {
            get
            {
                if (CurrentColumnView.OptionsSelection.MultiSelect)//多选模式
                {
                    return CurrentColumnView.GetSelectedRows().Length == 1;
                }
                else//单选模式
                {
                    return CurrentColumnView.FocusedRowHandle > -1;
                }
            }
        }

        /// <summary>
        /// 是否选中数据(单选或者多选)
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool HasSelected
        {
            get
            {
                //if (CurrentColumnView.OptionsSelection.MultiSelect)//多选模式
                //{
                //    return CurrentColumnView.GetSelectedRows().Length > 0;
                //}
                //单选模式
                return CurrentColumnView.FocusedRowHandle > -1;
            }
        }

        /// <summary>
        /// 选中的对象
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public object Selected => GetObject(SelectedIndex);

        /// <summary>
        /// 获取选中的对象列表
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public List<object> SelectedList
        {
            get
            {
                var list = new List<object>();
                foreach (var item in SelectedIndexList)
                {
                    if (item < 0) continue;
                    list.Add(GetObject(item));
                }
                return list;
            }
        }

        #endregion

        #region 公共方法

        public void BeginDataLoading()
        {
            isDataLoading = true;
            if (PagingControl is GridControlStandardPaging standardPaging) standardPaging.DataLoading = isDataLoading;
            if (PagingControl is GridControlInfinitePaging infinitePaging) infinitePaging.DataLoading = isDataLoading;

        }

        public void EndDataLoading()
        {
            isDataLoading = false;
            if (PagingControl is GridControlStandardPaging standardPaging) standardPaging.DataLoading = isDataLoading;
            if (PagingControl is GridControlInfinitePaging infinitePaging) infinitePaging.DataLoading = isDataLoading;
        }

        /// <summary>
        /// 根据列信息获取行索引
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="columnValue">列值</param>
        public int GetRowIndexByColumn(string columnName, string columnValue)
        {
            for (int i = 0; i < CurrentColumnView.DataRowCount; i++)
            {
                var value = CurrentColumnView.GetRowCellValue(i, columnName);
                if (value.ToStringOrEmpty().Equals(columnValue.ToStringOrEmpty()))
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 获取选中行的最后一行索引
        /// </summary>
        public int GetLastSelectedRowIndex()
        {
            var sz = CurrentColumnView.GetSelectedRows();
            var count = sz.Length;
            if (count > 0)
            {
                return sz[count - 1];
            }
            return -1;
        }

        /// <summary>
        /// 选中单行
        /// </summary>
        /// <param name="rowIndex">行索引</param>
        public void SelectSingleRow(int rowIndex)
        {
            CurrentColumnView.FocusedRowHandle = rowIndex;
            CurrentColumnView.SelectRow(rowIndex);
            if (MainView is GridView gridView)
            {
                gridView.MakeRowVisible(rowIndex);
            }
        }

        /// <summary>
        /// 清除选中的行
        /// </summary>
        public void ClearSelectRow()
        {
            CurrentColumnView.ClearSelection();
            CurrentColumnView.FocusedRowHandle = -1;
        }

        /// <summary>
        /// 获取主键值
        /// </summary>
        /// <param name="rowHandle">行索引</param>
        public string GetRecordId(int rowHandle)
        {
            if (rowHandle < 0) return null;

            var keyName = PrimaryKeyFieldName;
            if (string.IsNullOrEmpty(keyName))
            {
                throw new ArgumentException("请指定主键字段名,如果是GridViewPlus视图,则读取GridViewPlus的PrimaryKeyFieldName属性");
            }
            return CurrentColumnView.GetRowCellValue(rowHandle, keyName).ToStringOrEmpty();
        }

        /// <summary>
        /// 获取指定行的对象
        /// </summary>
        /// <param name="rowHandle">行索引号</param>
        public object GetObject(int rowHandle)
        {
            if (rowHandle < 0) return null;
            return CurrentColumnView.GetRow(rowHandle);
        }


        /// <summary>
        /// 获取当前焦点行对象
        /// </summary>
        public object GetSelectedObject()
        {
            var rowHandle = SelectedIndex;
            if (rowHandle < 0) return null;
            return CurrentColumnView.GetRow(rowHandle);
        }

        /// <summary>
        /// 获取当前焦点行对象
        /// </summary>
        public List<object> GetSelectedList()
        {
            var list = new List<object>();
            foreach (var rowHandle in SelectedIndexList)
            {
                if (rowHandle < 0) continue;
                list.Add(CurrentColumnView.GetRow(rowHandle));
            }
            return list;
        }

        /// <summary>
        /// 选中指定的行
        /// </summary>
        /// <param name="rowIndex">序号</param>
        public void SelectRowByIndex(int rowIndex)
        {
            if (rowIndex <= -1) return;
            CurrentColumnView.SelectRow(rowIndex);
            CurrentColumnView.FocusedRowHandle = rowIndex;
        }

        /// <summary>
        /// 选中行使用主键
        /// </summary>
        /// <param name="id">主键</param>
        public void SelectRowById(string id)
        {
            if (id.IsEmpty()) return;
            var rowIndex = GetRowIndexById(id);
            SelectRowByIndex(rowIndex);
        }

        /// <summary>
        /// 根据主键获取行索引
        /// </summary>
        /// <param name="id">主键</param>
        public int GetRowIndexById(string id)
        {
            if (id == null) return -1;
            var keyName = PrimaryKeyFieldName;
            for (var i = 0; i < CurrentColumnView.DataRowCount; i++)
            {
                var pkValue = CurrentColumnView.GetRowCellValue(i, keyName);
                if (pkValue.ToString().Equals(id))
                {
                    return i;
                }
            }
            return -1;
        }

        #endregion

        protected override async void OnCreateControl()
        {
            base.OnCreateControl();
            if (WinFormHelper.IsDesignMode()) return;

            try
            {
                isInit = false;

                OnBeforeInitialize();

                //初始化自绘行号事件
                InitDrawRowNumber();

                //初始化数据为空时的消息提示
                InitDrawEmptyDataMessage();

                //初始化表格过滤控件
                InitFilterEdit();

                //允许通过方向键移动表格焦点行
                InitKeyboardMoveFocusRow();

                //初始化服务端排序
                InitServerSorting();

                //双击表格行
                InitDoubleClick();

                //初始化右键菜单
                InitPopupMenu();

                //初始化表格分页
                InitPaging();

                //初始化表格选中行事件
                InitRowSelectionChanged();

                //初始化表格配置
                InitGridSetting();

                //加载表格配置
                if (AutoLoadSetting)
                {
                    await LoadGridSetting();
                }

                OnAfterInitialize();
            }
            finally
            {
                isInit = true;
            }
        }

        public async Task LoadGridSetting()
        {
            if (SettingManager == null) SettingManager = new SettingStoreManager(this, Id);

            if (!string.IsNullOrEmpty(Id))
            {
                BeforeRestoreLayout?.Invoke(this, EventArgs.Empty);
                await SettingManager.LoadCurrentAsync();
                AfterRestoreLayout?.Invoke(this, EventArgs.Empty);
            }
            else
            {
                Debug.WriteLine("请指定有效的GridControlPlus-Id");
            }
        }

        public void InitGridSetting()
        {
            if (!IsGridView) return;
            var allowCustomization = AllowCustomSetting && AppDefaultSettings.AllowCustomGridControlSetting;
            if (!allowCustomization) return;

            this.CurrentGridView.PopupMenuShowing += (s, e) =>
            {
                if (e.MenuType != GridMenuType.Column) return;
                if (!(e.Menu is GridViewColumnMenu menu)) return;

                var customItem = new DXMenuItem("设置", (o, a) => ShowSettingForm(), R.GridSettingImage16) { BeginGroup = true };
                menu.Items.Add(customItem);
            };
            this.CurrentGridView.KeyDown += (s, e) =>
            {
                if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.F12)
                {
                    ShowSettingForm();
                    e.Handled = true;
                }
            };
        }

        /// <summary>
        /// 显示配置窗口
        /// </summary>
        public void ShowSettingForm()
        {
            var settingFrm = new FrmSettingGridForm();
            settingFrm.Init(this);
            settingFrm.Show();
        }

        /// <summary>
        /// 初始化自绘行号事件
        /// </summary>
        public void InitDrawRowNumber()
        {
            if (!IsGridView) return;
            this.CurrentGridView.CustomDrawRowIndicator += (o, e) =>
            {
                if (!this.CurrentGridView.OptionsView.ShowIndicator) return;
                if (!e.Info.IsRowIndicator || e.RowHandle < 0) return;
                int numbers = e.RowHandle + 1;
                //int maxRecord = this.CurrentColumnView.RowCount;
                if (PagingControl is GridControlStandardPaging standardPaging)
                {
                    numbers = ((standardPaging.PageIndex - 1) * standardPaging.PageSize) + (e.RowHandle + 1);
                    //maxRecord = standardPaging.CurrentPagingInfo.RecordEndIndex;
                }
                var numberText = numbers.ToString();
                e.Info.DisplayText = numberText;
                e.Info.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center;
                e.Info.ImageIndex = -1;
                //CalcIndicatorWidth(maxRecord);
            };
        }

        /// <summary>
        /// 自动计算序号宽度
        /// </summary>
        /// <param name="maxRecord">记录最大值</param>
        public void CalcIndicatorWidth(int maxRecord)
        {
            if (!IsGridView) return;
            if (!AllowCalcIndicatorWidth) return;
            var len = maxRecord.ToString().Length;
            if (currentMaxRecordLength == len) return;
            currentMaxRecordLength = len;
            var size = WinFormHelper.CalcTextSize(maxRecord + "0", WindowsFormsSettings.DefaultFont);
            var w = size.Width;
            //if (w < 30) w = 30;

            CurrentGridView.IndicatorWidth = w;
        }

        /// <summary>
        /// 初始化数据为空时的消息提示
        /// </summary>
        public void InitDrawEmptyDataMessage()
        {
            if (!(MainView is IGridEmptyDataStyle view)) return;
            var font = new Font(AppearanceObject.DefaultFont.Name, 16, FontStyle.Regular);
            this.CurrentColumnView.CustomDrawEmptyForeground += (o, e) =>
            {
                if (isDataLoading || CurrentColumnView.RowCount > 0) return;
                if (view.AllowEmptyDataMessage && !string.IsNullOrEmpty(view.EmptyDataMessage))
                {
                    e.Appearance.Font = font;
                    e.Appearance.ForeColor = view.EmptyDataMessageColor;
                    e.DefaultDraw();
                    //显示位置
                    // Rectangle r = new Rectangle((this.Width - gridViewPlus.EmptyDataMessageSize.Width) / 2, (this.Height - gridViewPlus.EmptyDataMessageSize.Height) / 2, e.Bounds.Right - 5, e.Bounds.Height - 5);

                    var msg = view.EmptyDataMessage;
                    if (isDataLoading || !isInit)
                    {
                        msg = "正在加载...";
                    }
                    Size size = e.Appearance.CalcTextSize(e.Cache, view.EmptyDataMessage, e.Bounds.Width).ToSize();
                    Rectangle r = new Rectangle(new Point((e.Bounds.Width - size.Width) / 2, e.Bounds.Top + 45), size);
                    e.Appearance.DrawString(e.Cache, msg, r);
                    // e.Cache.DrawString(view.EmptyDataMessage, font, e.Cache.GetSolidBrush(view.EmptyDataMessageColor), r);
                    e.Handled = true;
                }
            };
        }

        /// <summary>
        /// 初始化表格过滤控件
        /// </summary>
        private void InitFilterEdit()
        {
            if (FilterEdit == null) return;
            if (!IsGridView) return;
            FilterEdit.KeyDown += (o, e) =>
            {
                if (e.KeyCode == Keys.Up)
                {
                    e.Handled = true;
                    CurrentGridView.MovePrev();
                }
                else if (e.KeyCode == Keys.Down)
                {
                    e.Handled = true;
                    CurrentGridView.MoveNext();
                }
                else if (e.KeyData == Keys.Escape)
                {
                    FilterEdit.Text = string.Empty;
                }
            };

            FilterEdit.KeyPress += (o, e) =>
            {
                if (e.KeyChar == R.EnterKey)
                {
                    CurrentColumnView.ApplyFindFilter(FilterEdit.Text?.Trim());
                    e.Handled = true;
                }
            };
        }

        /// <summary>
        /// 初始化方向键移动表格焦点行
        /// </summary>
        public void InitKeyboardMoveFocusRow()
        {
            this.KeyDown += (o, e) =>
            {
                if (!IsGridView) return;
                if (CurrentGridView.OptionsSelection.MultiSelect && CurrentGridView.OptionsSelection.MultiSelectMode == GridMultiSelectMode.CheckBoxRowSelect)
                {
                    if (e.KeyCode == Keys.Up)
                    {
                        this.CurrentGridView.MovePrev();
                        e.Handled = true;
                    }
                    else if (e.KeyCode == Keys.Down)
                    {
                        this.CurrentGridView.MoveNext();
                        e.Handled = true;
                    }
                }
            };
        }

        /// <summary>
        /// 初始化服务端排序
        /// </summary>
        public void InitServerSorting()
        {
            if (!AllowServerSorting || PagingControl is GridControlInfinitePaging) return;
            if (MainView is GridViewPlus gridViewPlus)
            {
                gridViewPlus.ColumnSortInfoChanged += async (o, e) =>
                {
                    if (isSorting) return;
                    try
                    {
                        isSorting = true;
                        await LoadAsync();
                    }
                    finally
                    {
                        isSorting = false;
                    }
                };
            }
        }

        private void OnRowSelectionChanged()
        {
            if (this.IsDisposed || this.MainView == null) return;
            RowSelectionChanged?.Invoke(this, EventArgs.Empty);
        }

        /// <summary>
        /// 初始化表格选中行事件
        /// </summary>
        private void InitRowSelectionChanged()
        {
            CurrentColumnView.SelectionChanged += (o, e) => OnRowSelectionChanged();
        }

        /// <summary>
        /// 初始化右键菜单
        /// </summary>
        private void InitPopupMenu()
        {
            if (!IsGridView) return;
            var menuManager = MenuManager;
            if (menuManager == null) return;
            if (AutoPopupMenu && PopupMenu == null)
            {
                PopupMenu = new PopupMenu();
                var barManager = (BarManager)menuManager;
                PopupMenu.Manager = barManager;
                foreach (BarItem item in barManager.Items)
                {
                    if (!(item is BarButtonItem)) continue;
                    PopupMenu.ItemLinks.Add(item);
                }
            }

            //注册右键显示事件
            CurrentGridView.MouseUp += (o, e) =>
            {
                if (PopupMenu == null) return;
                var hi = CurrentGridView.CalcHitInfo(e.Location);
                if (e.Button == MouseButtons.Right
                    && (hi.HitTest == GridHitTest.EmptyRow
                        || hi.HitTest == GridHitTest.Row
                        || hi.HitTest == GridHitTest.RowCell))
                {
                    PopupMenu.ShowPopup(Control.MousePosition);
                }
            };
        }

        /// <summary>
        /// 初始化表格分页
        /// </summary>
        private void InitPaging()
        {
            if (PagingControl == null) return;
            if (PagingControl is GridControlStandardPaging standardPaging)
            {
                standardPaging.LoadPagingData += async (o, e) => { await LoadStandardPagingData(e.PageFilter); };
            }
            else if (PagingControl is GridControlInfinitePaging infinitePaging)
            {
                _virtualServerModeSource = new VirtualServerModeSource();
                if (ModelType != null) _virtualServerModeSource.RowType = _modelType;
                _virtualServerModeSource.ConfigurationChanged += (o, eg) =>
                {
                    if (_virtualServerModeSourceInit) return;
                    _virtualSourcePageIndex = 0;
                };

                _virtualServerModeSource.MoreRows += (o, eg) =>
                {
                    if (_virtualServerModeSourceInit) return;
                    if (isDataLoading) return;
                    _virtualSourcePageIndex++;
                    var pageFilter = new BasePageFilter(_virtualSourcePageIndex, infinitePaging.PageSize);
                    if (eg.ConfigurationInfo.SortInfo?.Length > 0)
                    {
                        var sortInfo = eg.ConfigurationInfo.SortInfo[0];
                        pageFilter.SortName = sortInfo.SortPropertyName;
                        pageFilter.SortDir = sortInfo.IsDesc ? "desc" : "asc";
                    }

                    eg.RowsTask = LoadInfinitePagingData(pageFilter);
                };
                _virtualServerModeSourceInit = true;
                this.DataSource = _virtualServerModeSource;
                _virtualServerModeSourceInit = false;
            }
        }

        /// <summary>
        /// 初始化表格行双击事件
        /// </summary>
        public void InitDoubleClick()
        {
            if (!IsGridView) return;
            if (RowDoubleClick == null) return;
            this.CurrentGridView.DoubleClick += (o, e) =>
            {
                if (!(e is DXMouseEventArgs ev)) return;
                var info = this.CurrentGridView.CalcHitInfo(ev.Location);
                //必须是左键双击
                if (ev.Button == MouseButtons.Right) return;
                if (ev.Clicks == 2
                    && (info.HitTest == GridHitTest.Row || info.HitTest == GridHitTest.RowCell)
                    && this.CurrentGridView.FocusedRowHandle > -1)
                {
                    RowDoubleClick?.Invoke(this, EventArgs.Empty);
                }
            };
        }

        /// <summary>
        /// 自动生成表格列
        /// </summary>
        public void AutoBuildColumn()
        {
            if (!IsGridView) return;
            var modelInfo = ApiModelInfo;
            if (modelInfo == null) return;

            CurrentGridView.OptionsView.ShowGroupPanel = false;
            CurrentGridView.OptionsView.ColumnAutoWidth = false;
            CurrentGridView.OptionsBehavior.Editable = false;
            CurrentGridView.OptionsCustomization.AllowFilter = false;
            CurrentGridView.OptionsSelection.EnableAppearanceHideSelection = false;
            CurrentGridView.OptionsSelection.EnableAppearanceFocusedCell = false;
            CurrentGridView.OptionsSelection.EnableAppearanceFocusedRow = true;
            CurrentGridView.OptionsSelection.MultiSelect = true;
            CurrentGridView.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect;
            CurrentGridView.OptionsSelection.ResetSelectionClickOutsideCheckboxSelector = true;
            CurrentGridView.OptionsSelection.CheckBoxSelectorColumnWidth = 30;
            CurrentGridView.BorderStyle = BorderStyles.NoBorder;
            CurrentGridView.IndicatorWidth = 30;
            CurrentGridView.RowHeight = 30;
            CurrentGridView.FocusRectStyle = DrawFocusRectStyle.None;
            CurrentGridView.OptionsBehavior.AutoPopulateColumns = false;
            CurrentGridView.Columns.Clear();

            int index = 0;
            foreach (var item in modelInfo.Propertys)
            {
                var col = item;
                GridColumn column = new GridColumn();
                if (IsBandedGridView)
                {
                    var bcol = new BandedGridColumn();
                    column = bcol;
                    if (CurrentBandedGridView.Bands.Count > 0)
                    {
                        var band = CurrentBandedGridView.Bands.FirstVisibleBand;
                        band.Columns.Add(bcol);
                    }
                }
                column.VisibleIndex = index + 1;
                column.Name = $"col_{item.Name}";
                column.FieldName = col.Name;
                column.Caption = col.Caption ?? col.Name;
                column.OptionsColumn.AllowEdit = false;

                //column.AppearanceCell.Options.UseTextOptions = true;
                //column.AppearanceCell.TextOptions.HAlignment = HorzAlignment.Center;
                //column.AppearanceHeader.Options.UseTextOptions = true;
                //column.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center;

                var dataType = col.Property.PropertyType;
                if (dataType == typeof(DateTime) || dataType == typeof(DateTime?))
                {
                    column.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime;
                    column.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss";
                }
                else if (dataType == typeof(decimal) || dataType == typeof(decimal?))
                {
                    column.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric;
                    column.DisplayFormat.FormatString = "#.##";
                }

                column.Visible = col.Visable;
                CurrentGridView.Columns.Add(column);


                index++;
            }
            CurrentGridView.BestFitColumns();
        }

        public void InvokeRowSelectionChanged()
        {
            OnRowSelectionChanged();
        }

        public void InvokeRowDoubleClick()
        {
            RowDoubleClick?.Invoke(this, EventArgs.Empty);
        }

        protected object OnDetectFilter(BasePageFilter pageFilter)
        {
            var args = new DetectFilterEventArgs { PageFilter = pageFilter };
            DetectFilter?.Invoke(this, args);
            if (args.ValidateFilter && args.Filter != null)
            {
                App.Validator.ValidateObject(args.Filter);
            }
            if (pageFilter != null && args.Filter != null)
            {
                if (args.Filter is BasePageFilter pfilter)
                {
                    pfilter.CombinePageFilter(pageFilter);
                }
                else if(args.Filter is IPageParam pageParam)
                {
                    pageParam.PageFilter = pageFilter;
                }
            }
            return args.Filter;
        }

        /// <summary>
        /// 获取表格过滤对象
        /// </summary>
        public object GetFilter()
        {
            return OnDetectFilter(GetPageFilter());
        }

        /// <summary>
        /// 获取分页过滤对象
        /// </summary>
        public BasePageFilter GetPageFilter()
        {
            BasePageFilter pageFilter = null;
            if (PagingControl is GridControlInfinitePaging infinitePaging)
            {
                pageFilter = new BasePageFilter(_virtualSourcePageIndex, infinitePaging.PageSize);
            }
            else if (PagingControl is GridControlStandardPaging standardPaging)
            {
                pageFilter = standardPaging.CurrentPageFilter;
            }

            return pageFilter;
        }

        /// <summary>
        /// 确认更新当前行状态
        /// </summary>
        public bool ValidEditColumn(string fieldName)
        {
            if (CurrentColumnView.FocusedRowHandle < 0) return false;

            var col = CurrentColumnView.FocusedColumn;
            if (col.FieldName.Equals(fieldName))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 删除选中的数据
        /// </summary>
        public async Task DeleteAsync(string confirmMessage = null)
        {
            int count = CurrentColumnView.GetSelectedRows().Length;
            if (count == 0)
            {
                MessageBoxHelper.ShowError("请选择需要操作的数据");
                return;
            }
            if (string.IsNullOrEmpty(confirmMessage))
            {
                confirmMessage = $"确定要删除选中的 {count} 行数据吗?";
            }
            if (MessageBoxHelper.ShowWarnYesNo(confirmMessage) != DialogResult.Yes)
            {
                return;
            }

            if (DeleteData == null) throw new ArgumentException("请指定删除数据事件");
            var args = new DeleteDataEventArgs();
            DeleteData.Invoke(this, args);
            if (args.Task == null) return;
            await args.Task.Invoke();
            CurrentColumnView.DeleteSelectedRows();
            await LoadAsync();
        }

        private int GetActualPageIndexCore(int? pageIndex = null)
        {
            var index = 1;
            if (pageIndex.HasValue)
            {
                index = pageIndex.Value;
            }
            else if (PagingControl is GridControlStandardPaging standardPaging)
            {
                index = standardPaging.CurrentPagingInfo?.PageIndex ?? 1;
            }

            return index;
        }

        public async Task LoadFirstPageAsync()
        {
            await LoadAsync(1);
        }

        public async Task LoadAsync(int? pageIndex = null)
        {
            if (WinFormHelper.IsDesignMode()) return;
            if (isDataLoading) return;
            if (PagingControl is GridControlInfinitePaging)
            {
                RefreshDataSource();
            }
            else if (PagingControl is GridControlStandardPaging standardPaging)
            {
                standardPaging.LoadData(GetActualPageIndexCore(pageIndex));
            }
            else
            {
                await LoadDataWrap(async () =>
                {
                    var dataSourceResult = await LoadPagingDataCore(null);
                    if (dataSourceResult != null)
                    {
                        this.DataSource = dataSourceResult.GetRows();
                        CalcIndicatorWidth(dataSourceResult.GetTotal());
                    }
                    else
                    {
                        this.DataSource = null;
                    }
                });
            }
        }

        private PagingInfo GetPagingInfo(IPagingList pagingList)
        {
            return pagingList.GetTotal() == 0 ?
                new PagingInfo(pagingList.GetPageIndex(), pagingList.GetPageSize(), 0)
                : new PagingInfo(pagingList.GetPageIndex(), pagingList.GetPageSize(), pagingList.GetTotal());
        }

        private async Task LoadStandardPagingData(BasePageFilter pageFilter)
        {
            if (CurrentColumnView == null || CurrentColumnView.IsDisposing
                                          || this.Disposing || this.IsDisposed
                                          || PagingControl == null
                                          || PagingControl.Disposing || PagingControl.IsDisposed) return;
            if (CurrentColumnView.SortInfo.Count > 0)
            {
                var sortInfo = CurrentColumnView.SortInfo[0];
                var sname = sortInfo.Column.FieldName;
                pageFilter.SortName = sname;
                pageFilter.SortDir = sortInfo.SortOrder == ColumnSortOrder.Ascending ? "asc" : "desc";
            }

            await LoadDataWrap(async () =>
            {
                var dataSourceResult = await LoadPagingDataCore(pageFilter);
                if (dataSourceResult != null)
                {
                    this.DataSource = dataSourceResult.GetRows();
                    var pageInfo = GetPagingInfo(dataSourceResult);
                    CalcIndicatorWidth(pageInfo.RecordEndIndex);
                    ((GridControlStandardPaging)PagingControl).BindingInfo(pageInfo);
                }
                else
                {
                    this.DataSource = null;
                    var pcontrol = (GridControlStandardPaging)PagingControl;
                    pcontrol.BindingInfo(new PagingInfo(1, pcontrol.PageSize, 0));
                }
            });
        }

        private async Task<VirtualServerModeRowsTaskResult> LoadInfinitePagingData(BasePageFilter pageFilter)
        {
            if (CurrentColumnView == null || CurrentColumnView.IsDisposing
                 || this.Disposing || this.IsDisposed
                 || PagingControl == null 
                 || PagingControl.Disposing || PagingControl.IsDisposed) return null;
            VirtualServerModeRowsTaskResult result = null;
            await LoadDataWrap(async () =>
            {
                var dataSourceResult = await LoadPagingDataCore(pageFilter);
                if (dataSourceResult?.GetRows() == null)
                {
                    result = new VirtualServerModeRowsTaskResult(null, false);
                    var icontrol = (GridControlInfinitePaging)PagingControl;
                    ((GridControlInfinitePaging)PagingControl).BindingInfo(new PagingInfo(1, icontrol.PageSize, 0));
                }
                else
                {
                    var pageInfo = GetPagingInfo(dataSourceResult);
                    var hasMoreRows = pageInfo.HasNextPage;
                    CalcIndicatorWidth(pageInfo.RecordEndIndex);
                    ((GridControlInfinitePaging)PagingControl).BindingInfo(pageInfo);
                    result = new VirtualServerModeRowsTaskResult(dataSourceResult.GetRows(), hasMoreRows);
                }
            });
            return result;
        }

        private async Task<IPagingList> LoadPagingDataCore(BasePageFilter pageFilter)
        {
            var gridFilter = OnDetectFilter(pageFilter);

            var args = new LoadDataEventArgs { PageFilter = pageFilter, Filter = gridFilter };
            BeforeLoadData?.Invoke(this, args);

            if (LoadData == null) return null;
            LoadData.Invoke(this, args);
            if (args.Task == null) return null;
            var dataSource = await args.Task.Invoke();

            AfterLoadData?.Invoke(this, new AfterLoadPagingDataEventArgs
            {
                PageFilter = pageFilter,
                Filter = gridFilter,
                DataSource = dataSource
            });

            //数据加载成功后
            if (dataSource != null && ModelType == null)
            {
                var rows = dataSource.GetRows();
                if (rows != null && rows.Count > 0)
                {
                    var firstRow = rows[0];
                    this.ModelType = firstRow.GetType();
                    if (_virtualServerModeSource != null) _virtualServerModeSource.RowType = ModelType;
                }
            }
            return dataSource;
        }

        private async Task LoadDataWrap(Func<Task> callback)
        {
            try
            {
                BeginDataLoading();
                if (IsShowDataLoadingPanel && MainView is GridView gridView) gridView.ShowLoadingPanel();
                sw.Reset();
                sw.Start();
                ElapsedTimeSpan = TimeSpan.Zero;

                await callback.Invoke();
            }
            finally
            {
                EndDataLoading();
                sw.Stop();
                if (IsShowDataLoadingPanel && MainView is GridView gridView) gridView.HideLoadingPanel();
                ElapsedTimeSpan = sw.Elapsed;
                if (ElapsedTimeItem != null) ElapsedTimeItem.Caption = $"{sw.Elapsed.TotalMilliseconds:###0.##} ms";
                if (ElapsedTimeControl != null) ElapsedTimeControl.Text = $"{sw.Elapsed.TotalMilliseconds:###0.##} ms";

                OnRowSelectionChanged();
            }
        }

        #region Implementation of ISettingSerializer

        /// <summary>
        /// 保存控件配置
        /// </summary>
        /// <param name="xmlFile">xml文件路径</param>
        public void SaveLayout(string xmlFile)
        {
            if (this.MainView is ISettingSerializer currentView)
            {
                currentView.SaveLayout(xmlFile);
            }
        }

        /// <summary>
        /// 加载配置到控件
        /// </summary>
        /// <param name="xmlFile">xml文件路径</param>
        public void RestoreLayout(string xmlFile)
        {
            if (this.MainView is ISettingSerializer currentView)
            {
                currentView.RestoreLayout(xmlFile);
            }
        }

        #endregion
    }


    public class LoadDataEventArgs : EventArgs
    {
        /// <summary>
        /// 分页请求信息
        /// </summary>
        public BasePageFilter PageFilter { get; set; }

        /// <summary>
        /// 获取或者设置表格过滤对象
        /// </summary>
        public object Filter { get; set; }

        public Func<Task<IPagingList>> Task { get; set; }
    }

    public class AfterLoadPagingDataEventArgs : EventArgs
    {
        /// <summary>
        /// 分页请求信息
        /// </summary>
        public BasePageFilter PageFilter { get; internal set; }

        /// <summary>
        /// 获取或者设置表格过滤对象
        /// </summary>
        public object Filter { get; set; }

        public IPagingList DataSource { get; set; }
    }

    public class DeleteDataEventArgs : EventArgs
    {
        public Func<Task> Task { get; set; }
    }

    public class FormatPagingMessageEventArgs : EventArgs
    {
        /// <summary>
        /// 分页信息
        /// </summary>
        public PagingInfo PagingInfo { get; internal set; }

        public string PagingMessage { get; set; }
    }

    public class DetectFilterEventArgs : EventArgs
    {
        /// <summary>
        /// 分页过滤对象
        /// </summary>
        public BasePageFilter PageFilter { get; set; }

        /// <summary>
        /// 获取或者设置表格过滤对象
        /// </summary>
        public object Filter { get; set; }

        /// <summary>
        /// 验证过滤条件
        /// </summary>
        public bool ValidateFilter { get; set; } = true;
    }

    public interface IGridEmptyDataStyle
    {
        /// <summary>
        /// 是否允许在未加载到数据时显示消息
        /// </summary>
        bool AllowEmptyDataMessage { get; set; }

        /// <summary>
        /// 空数据时显示消息
        /// </summary>
        string EmptyDataMessage { get; set; }

        /// <summary>
        /// 空数据时显示消息颜色
        /// </summary>
        Color EmptyDataMessageColor { get; set; }

        /// <summary>
        /// 空数据时消息尺寸
        /// </summary>
        Size EmptyDataMessageSize { get; }
    }
}
